package com.zs.propertymanage.service.impl.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zs.propertymanage.dataObj.DTO;
import com.zs.propertymanage.dataObj.GeneralExtra;
import com.zs.propertymanage.dataObj.R;
import com.zs.propertymanage.dataObj.entity.Employee;
import com.zs.propertymanage.dataObj.entity.Message;
import com.zs.propertymanage.dataObj.entity.PatrolTask;
import com.zs.propertymanage.dataObj.entity.WorkOrder;
import com.zs.propertymanage.dataObj.param.FormedEmployee;
import com.zs.propertymanage.dataObj.param.StatisticItem;
import com.zs.propertymanage.dataObj.workorderExtra.WorkOrderCategory;
import com.zs.propertymanage.dataObj.workorderExtra.WorkOrderProcess;
import com.zs.propertymanage.mapper.EmployeeMapper;
import com.zs.propertymanage.mapper.MessageMapper;
import com.zs.propertymanage.mapper.PatrolMapper;
import com.zs.propertymanage.mapper.WorkOrderMapper;
import com.zs.propertymanage.service.impl.EmployeeService;
import com.zs.propertymanage.service.impl.OrgService;
import com.zs.propertymanage.utils.MD5Util;
import com.zs.propertymanage.websocket.WebSocketService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

@Service
public class EmployeeServiceImpl implements EmployeeService {


    @Autowired
    private EmployeeMapper employeeMapper;
    @Autowired
    private WorkOrderMapper workOrderMapper;
    @Autowired
    private PatrolMapper patrolMapper;
    @Autowired
    private OrgService orgService;
    @Autowired
    private MessageMapper messageMapper;

    @Override
    public R getAllEmployee() {
        List<Employee> list = employeeMapper.getAll();
        return list.size() > 0 ? R.ok("查询员工列表成功", list) : R.error("查询员工列表失败");
    }

    @Override
    public R getAllEmployeeWithExtra(String search, Integer currentPage, Integer pageSize) {
        // 计算查询的起始条数
        Integer start = (currentPage - 1) * pageSize;
        Integer total = employeeMapper.getCountWithCondition(search, start, pageSize);
        List<Employee> list = employeeMapper.getAllWithExtra(search, start, pageSize);
        // 封装查询结果
        DTO<Employee> dto = new DTO<>(list, total);
        return total > 0 ? R.ok("查询员工信息列表成功", dto) : R.error("查询员工信息列表失败");
    }

    @Override
    public R getAllEmployeeOrg() {
        List<GeneralExtra> list = employeeMapper.getAllEmpOrg();
        return list.size() > 0 ? R.ok("查询员工组织列表成功", list) : R.error("查询员工组织列表失败");
    }

    @Override
    public R getAllEmployeeRole() {
        List<GeneralExtra> list = employeeMapper.getAllEmpRole();
        return list.size() > 0 ? R.ok("查询员工角色列表成功", list) : R.error("查询员工角色列表失败");
    }

    @Override
    public R addEmployee(Employee employee) {
        String pwd = employee.getPassword();
        // 密码MD5加密
        if (pwd != null && !pwd.equals("")) {
            employee.setPassword(MD5Util.MD5Encrypt(pwd));
        } else {
            return R.error("密码不能为空");
        }
        employee.setId(UUID.randomUUID().toString());
        Integer result = employeeMapper.addEmployee(employee);
        return result > 0 ? R.ok("添加员工成功") : R.error("添加员工失败");
    }

    @Override
    public R updateEmployee(Employee employee) {
        Integer result = employeeMapper.updateEmployee(employee);
        return result > 0 ? R.ok("更新员工信息成功") : R.error("更新员工信息失败");
    }

    @Override
    public R deleteEmployee(String id) {
        Integer result = employeeMapper.deleteEmployee(id);
        return result > 0 ? R.ok("删除员工成功") : R.error("删除员工失败");
    }

    @Override
    public R deleteEmployeeRoleById(Integer id) {
        Integer result = employeeMapper.deleteEmployeeRoleById(id);
        return result > 0 ? R.ok("删除员工角色成功") : R.error("删除员工角色失败");
    }

    @Override
    public R addEmployeeRole(String roleName) {
        if (roleName == null || roleName.equals("")) {
            return R.error("添加失败，员工角色名称不能为空");
        }
        Integer result = employeeMapper.addEmployeeRole(roleName);
        return result > 0 ? R.ok("添加员工角色成功") : R.error("添加员工角色失败");
    }

    @Override
    public R deleteEmployeeOrgById(Integer id) {
        Integer result = employeeMapper.deleteEmployeeOrgById(id);
        return result > 0 ? R.ok("删除员工组织成功") : R.error("删除员工组织失败");
    }

    @Override
    public R addEmployeeOrg(String orgName) {
        if (orgName == null || orgName.equals("")) {
            return R.error("添加失败，员工组织名称不能为空");
        }
        Integer result = employeeMapper.addEmployeeOrg(orgName);
        return result > 0 ? R.ok("添加员工组织成功") : R.error("添加员工组织失败");
    }

    @Override
    public R getUnreceivedWorkOrder(String employeeId) {

        Employee employee = employeeMapper.getEmployeeById(employeeId);
        Integer orgId = employee.getOrgId();

        List<Integer> resultOrgList = orgService.getChildrenIdList(orgId);

        // 查询该员工有职责的工单分类
        List<WorkOrderCategory> dutyCategoryList = workOrderMapper.getDutyCategory(employeeId);

        List<WorkOrder> dutyWorkOrderList = new ArrayList<>();
        // 按工单分类查询未被接收的工单
        for (WorkOrderCategory category : dutyCategoryList) {
            List<WorkOrder> workOrders = workOrderMapper.getUnreceivedWorkOrderByCategoryIdAndOrgId(category.getId(), resultOrgList);
            if (workOrders != null) dutyWorkOrderList.addAll(workOrders);
        }

        // 按照orderTime字段对未接收工单列表进行升序排序
        dutyWorkOrderList.sort(Comparator.comparing(WorkOrder::getOrderTime));

        return dutyWorkOrderList.size() > 0 ? R.ok("刷新接单大厅成功~", dutyWorkOrderList) : R.error("接单大厅暂无工单~");
    }

    @Override
    public R receiveWorkOrder(String employeeId, String workOrderId) {
        Employee handler = employeeMapper.getEmployeeById(employeeId);
        WorkOrder workOrder = workOrderMapper.getWorkOrderById(workOrderId);
        workOrder.setCompleteStatus(2); // 1-待接收 2-处理中 3-已完成
        workOrder.setCurrentHandlerId(employeeId);
        workOrder.setCurrentHandlerName(handler.getName());
        workOrder.setCurrentHandleTime(LocalDateTime.now());

        Integer result = workOrderMapper.handleWorkOrder(workOrder);
        // 消息通知到租户
        if (result > 0) {
            Message message = new Message(
                    UUID.randomUUID().toString(),
                    "工单已被接收",
                    LocalDateTime.now(),
                    "[" + handler.getRoleName() + "]" + handler.getName() + " : " + "您的工单已被接收，即将开始处理",
                    Message.TYPE_TENANT,
                    workOrder.getSubmitterId(),
                    Message.TYPE_EMPLOYEE,
                    workOrder.getCurrentHandlerId()
            );
            messageMapper.addMessage(message);
            WebSocketService.sendTextMessage(workOrder.getSubmitterId(), "您有工单已被接收了~");    // 人员id改为了uuid，具有唯一性，不需要附加身份了

        }
        return result > 0 ? R.ok("接收工单成功") : R.error("接收工单失败");
    }

    @Override
    public R getReceivedWorkOrder(String employeeId, String search, Integer currentPage, Integer pageSize) {
        Integer start = (currentPage - 1) * pageSize;
        List<WorkOrder> list = workOrderMapper.getReceivedWorkOrder(employeeId, search, start, pageSize);
        Integer total = workOrderMapper.getCountOfEmployeeByCompleteStatus(employeeId, WorkOrder.COMPLETE_STATUS_PROCESSING);
        total = total + workOrderMapper.getCountOfEmployeeByCompleteStatus(employeeId, WorkOrder.COMPLETE_STATUS_COMPLETED);
        return total > 0 ? R.ok("查询已接收工单列表成功", new DTO<>(list, total)) : R.error("未查询到已接收工单");
    }

    @Override
    public R handleWorkOrder(String employeeId, String workOrderId, String handleRemark) {

        // 获取当前要处理的工单对象
        WorkOrder workOrder = workOrderMapper.getWorkOrderById(workOrderId);
        // 获取process并且解析为WorkOrderProcess集合
        String processStr = workOrder.getProcess();
        String[] processArr = processStr.split("&process-split&");

        Employee handler = employeeMapper.getEmployeeById(employeeId);

        StringBuilder processList = new StringBuilder();
        ObjectMapper objectMapper = new ObjectMapper();
        int flowFlag = 0;   // 判断是否是第一条记录
        boolean isFinalFlow = false;  // 是否是最后一个流程节点
        for (int i = 0; i < processArr.length; i++) {   // 遍历每一个流程节点
            try {

                WorkOrderProcess process = objectMapper.readValue(processArr[i], WorkOrderProcess.class);
                if (process.getCompleteStatus() == 0 && flowFlag == 0) { // 找到第一个未完成的流程节点
                    flowFlag = 1;   // 只更新这一个流程节点
                    process.setStartTime(new Date().getTime());

                    process.setHandler(handler.getName());
                    process.setRemark(handleRemark);
                    process.setCompleteStatus(1);

                    if (i == processArr.length - 1) {    // 若当前处理的是最后一个流程节点
                        isFinalFlow = true;
                        workOrder.setCompleteStatus(3); // 设置完成状态为3 1-待接收 2-处理中 3-已完成
                    }
                }
                if (i == 0) processList.append(process);    // 首个节点不加连接符
                else processList.append("&process-split&").append(process); // 非首节点需加连接符

            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        workOrder.setProcess(processList.toString());
        Integer result = workOrderMapper.updateWorkOrder(workOrder);    // 更新数据库
        String completeInfo = isFinalFlow ? "[完成]" : "[处理]";
        // 消息通知到租户
        if (result > 0) {
            // 本次处理的不是最后一个节点，则消息通知“新进度”，否则消息通知“工单完成”
            Message message = new Message(
                    UUID.randomUUID().toString(),
                    isFinalFlow ? "工单已完成" : "新的工单进度",
                    LocalDateTime.now(),
                    "[" + handler.getRoleName() + "]" + handler.getName() + " : " + completeInfo + handleRemark,
                    Message.TYPE_TENANT,
                    workOrder.getSubmitterId(),
                    Message.TYPE_EMPLOYEE,
                    workOrder.getCurrentHandlerId()
            );
            messageMapper.addMessage(message);
            WebSocketService.sendTextMessage(workOrder.getSubmitterId(), isFinalFlow ? "您有工单已被处理完成了~" : "您的工单有新的处理进度了~");    // 人员id改为了uuid，具有唯一性，不需要附加身份了

        }

        return result > 0 ? R.ok("处理工单成功") : R.error("处理工单失败");

    }

    @Override
    public R getStatByEmployee(String employeeId) {
        TreeMap<String, List<StatisticItem>> resultMap = new TreeMap<>();

        // completeStatus: 1-待接收 2-处理中 3-已完成
        Integer completedWorkOrderCount = workOrderMapper.getCountOfEmployeeByCompleteStatus(employeeId, WorkOrder.COMPLETE_STATUS_COMPLETED);
        Integer processingWorkOrderCount = workOrderMapper.getCountOfEmployeeByCompleteStatus(employeeId, WorkOrder.COMPLETE_STATUS_PROCESSING);
        Integer completedPatrolTaskCount = patrolMapper.getCountOfEmployeeByCompleteStatus(employeeId, PatrolTask.COMPLETE_STATUS_COMPLETE);
        Integer incompletePatrolTaskCount = patrolMapper.getCountOfEmployeeByCompleteStatus(employeeId, PatrolTask.COMPLETE_STATUS_INCOMPLETE);

        StatisticItem completedWorkOrderStat = new StatisticItem("已完成", completedWorkOrderCount);
        StatisticItem processingWorkOrderStat = new StatisticItem("处理中", processingWorkOrderCount);
        StatisticItem incompletePatrolTaskStat = new StatisticItem("未完成", incompletePatrolTaskCount);
        StatisticItem completePatrolTaskStat = new StatisticItem("已完成", completedPatrolTaskCount);

        List<StatisticItem> workOrderStatList = new ArrayList<>();
        workOrderStatList.add(processingWorkOrderStat);
        workOrderStatList.add(completedWorkOrderStat);
        List<StatisticItem> patrolTaskStatList = new ArrayList<>();
        patrolTaskStatList.add(incompletePatrolTaskStat);
        patrolTaskStatList.add(completePatrolTaskStat);

        resultMap.put("workOrderStat", workOrderStatList);
        resultMap.put("patrolTaskStat", patrolTaskStatList);

        return R.ok("查询员工任务统计概览成功", resultMap);
    }

    @Override
    public R getEmployeeByRole() {

        List<GeneralExtra> employeeRoleList = employeeMapper.getAllEmpRole();

        List<FormedEmployee> empListByRole = new ArrayList<>();

        for (GeneralExtra employeeRole : employeeRoleList) {
            // 查询当前role下的员工列表
            List<GeneralExtra> empListByOneRole = employeeMapper.getEmpByRoleId(employeeRole.getId());
            if (empListByOneRole.size() == 0)
                continue;   // 若当前role下的员工列表为空，则跳过
            // 封装进FormedEmployee
            FormedEmployee formedEmployee = new FormedEmployee();
            formedEmployee.setLabel(employeeRole.getName());
            formedEmployee.setChildren(empListByOneRole);
            empListByRole.add(formedEmployee);
        }
        return R.ok("按角色查询员工列表成功", empListByRole);
    }

    @Override
    public R getEmployeeById(String id) {
        Employee employee = employeeMapper.getEmployeeById(id);
        return employee != null ? R.ok("查询员工信息成功", employee) : R.error("查询员工信息失败");
    }


}